Commit ac8bdabb authored by Ken Rockot's avatar Ken Rockot Committed by Commit Bot

Fix UAF in CachedStorageArea

CachedStorageArea is ref-counted and was retaining an unsafe reference
to a GCed object which it may outlive.

This changes that reference to a WeakPersistent and ensures that we
don't dereference it once it's no longer valid.

Fixed: 1048234
Change-Id: I9971b35b9aa7db790236f92c353a2320740f7729
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2036383
Commit-Queue: Ken Rockot <rockot@google.com>
Commit-Queue: Victor Costan <pwnall@chromium.org>
Reviewed-by: default avatarDaniel Murphy <dmurph@chromium.org>
Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
Auto-Submit: Ken Rockot <rockot@google.com>
Cr-Commit-Position: refs/heads/master@{#738424}
parent 71746349
...@@ -65,9 +65,10 @@ scoped_refptr<CachedStorageArea> CachedStorageArea::CreateForLocalStorage( ...@@ -65,9 +65,10 @@ scoped_refptr<CachedStorageArea> CachedStorageArea::CreateForLocalStorage(
scoped_refptr<const SecurityOrigin> origin, scoped_refptr<const SecurityOrigin> origin,
mojo::PendingRemote<mojom::blink::StorageArea> area, mojo::PendingRemote<mojom::blink::StorageArea> area,
scoped_refptr<base::SingleThreadTaskRunner> ipc_runner, scoped_refptr<base::SingleThreadTaskRunner> ipc_runner,
InspectorEventListener* listener) { StorageNamespace* storage_namespace) {
return base::AdoptRef(new CachedStorageArea( return base::AdoptRef(
std::move(origin), std::move(area), std::move(ipc_runner), listener)); new CachedStorageArea(std::move(origin), std::move(area),
std::move(ipc_runner), storage_namespace));
} }
// static // static
...@@ -75,9 +76,10 @@ scoped_refptr<CachedStorageArea> CachedStorageArea::CreateForSessionStorage( ...@@ -75,9 +76,10 @@ scoped_refptr<CachedStorageArea> CachedStorageArea::CreateForSessionStorage(
scoped_refptr<const SecurityOrigin> origin, scoped_refptr<const SecurityOrigin> origin,
mojo::PendingAssociatedRemote<mojom::blink::StorageArea> area, mojo::PendingAssociatedRemote<mojom::blink::StorageArea> area,
scoped_refptr<base::SingleThreadTaskRunner> ipc_runner, scoped_refptr<base::SingleThreadTaskRunner> ipc_runner,
InspectorEventListener* listener) { StorageNamespace* storage_namespace) {
return base::AdoptRef(new CachedStorageArea( return base::AdoptRef(
std::move(origin), std::move(area), std::move(ipc_runner), listener)); new CachedStorageArea(std::move(origin), std::move(area),
std::move(ipc_runner), storage_namespace));
} }
unsigned CachedStorageArea::GetLength() { unsigned CachedStorageArea::GetLength() {
...@@ -199,9 +201,9 @@ CachedStorageArea::CachedStorageArea( ...@@ -199,9 +201,9 @@ CachedStorageArea::CachedStorageArea(
scoped_refptr<const SecurityOrigin> origin, scoped_refptr<const SecurityOrigin> origin,
mojo::PendingRemote<mojom::blink::StorageArea> area, mojo::PendingRemote<mojom::blink::StorageArea> area,
scoped_refptr<base::SingleThreadTaskRunner> ipc_runner, scoped_refptr<base::SingleThreadTaskRunner> ipc_runner,
InspectorEventListener* listener) StorageNamespace* storage_namespace)
: origin_(std::move(origin)), : origin_(std::move(origin)),
inspector_event_listener_(listener), storage_namespace_(storage_namespace),
ipc_task_runner_(std::move(ipc_runner)), ipc_task_runner_(std::move(ipc_runner)),
mojo_area_remote_(std::move(area), ipc_task_runner_), mojo_area_remote_(std::move(area), ipc_task_runner_),
mojo_area_(mojo_area_remote_.get()), mojo_area_(mojo_area_remote_.get()),
...@@ -217,9 +219,9 @@ CachedStorageArea::CachedStorageArea( ...@@ -217,9 +219,9 @@ CachedStorageArea::CachedStorageArea(
scoped_refptr<const SecurityOrigin> origin, scoped_refptr<const SecurityOrigin> origin,
mojo::PendingAssociatedRemote<mojom::blink::StorageArea> area, mojo::PendingAssociatedRemote<mojom::blink::StorageArea> area,
scoped_refptr<base::SingleThreadTaskRunner> ipc_runner, scoped_refptr<base::SingleThreadTaskRunner> ipc_runner,
InspectorEventListener* listener) StorageNamespace* storage_namespace)
: origin_(std::move(origin)), : origin_(std::move(origin)),
inspector_event_listener_(listener), storage_namespace_(storage_namespace),
ipc_task_runner_(std::move(ipc_runner)), ipc_task_runner_(std::move(ipc_runner)),
mojo_area_associated_remote_(std::move(area), ipc_task_runner_), mojo_area_associated_remote_(std::move(area), ipc_task_runner_),
mojo_area_(mojo_area_associated_remote_.get()), mojo_area_(mojo_area_associated_remote_.get()),
...@@ -578,8 +580,10 @@ void CachedStorageArea::EnqueueStorageEvent(const String& key, ...@@ -578,8 +580,10 @@ void CachedStorageArea::EnqueueStorageEvent(const String& key,
} }
} }
areas_->RemoveAll(areas_to_remove_); areas_->RemoveAll(areas_to_remove_);
inspector_event_listener_->DidDispatchStorageEvent(origin_.get(), key, if (storage_namespace_) {
old_value, new_value); storage_namespace_->DidDispatchStorageEvent(origin_.get(), key, old_value,
new_value);
}
} }
// static // static
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h" #include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/storage/storage_area_map.h" #include "third_party/blink/renderer/modules/storage/storage_area_map.h"
#include "third_party/blink/renderer/modules/storage/storage_namespace.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h" #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
...@@ -56,26 +57,16 @@ class MODULES_EXPORT CachedStorageArea ...@@ -56,26 +57,16 @@ class MODULES_EXPORT CachedStorageArea
WebScopedVirtualTimePauser::VirtualTaskDuration duration) = 0; WebScopedVirtualTimePauser::VirtualTaskDuration duration) = 0;
}; };
// Used to send events to the InspectorDOMStorageAgent.
class InspectorEventListener {
public:
virtual ~InspectorEventListener() = default;
virtual void DidDispatchStorageEvent(const SecurityOrigin* origin,
const String& key,
const String& old_value,
const String& new_value) = 0;
};
static scoped_refptr<CachedStorageArea> CreateForLocalStorage( static scoped_refptr<CachedStorageArea> CreateForLocalStorage(
scoped_refptr<const SecurityOrigin> origin, scoped_refptr<const SecurityOrigin> origin,
mojo::PendingRemote<mojom::blink::StorageArea> area, mojo::PendingRemote<mojom::blink::StorageArea> area,
scoped_refptr<base::SingleThreadTaskRunner> ipc_runner, scoped_refptr<base::SingleThreadTaskRunner> ipc_runner,
InspectorEventListener* listener); StorageNamespace* storage_namespace);
static scoped_refptr<CachedStorageArea> CreateForSessionStorage( static scoped_refptr<CachedStorageArea> CreateForSessionStorage(
scoped_refptr<const SecurityOrigin> origin, scoped_refptr<const SecurityOrigin> origin,
mojo::PendingAssociatedRemote<mojom::blink::StorageArea> area, mojo::PendingAssociatedRemote<mojom::blink::StorageArea> area,
scoped_refptr<base::SingleThreadTaskRunner> ipc_runner, scoped_refptr<base::SingleThreadTaskRunner> ipc_runner,
InspectorEventListener* listener); StorageNamespace* storage_namespace);
// These correspond to blink::Storage. // These correspond to blink::Storage.
unsigned GetLength(); unsigned GetLength();
...@@ -104,12 +95,12 @@ class MODULES_EXPORT CachedStorageArea ...@@ -104,12 +95,12 @@ class MODULES_EXPORT CachedStorageArea
CachedStorageArea(scoped_refptr<const SecurityOrigin> origin, CachedStorageArea(scoped_refptr<const SecurityOrigin> origin,
mojo::PendingRemote<mojom::blink::StorageArea> area, mojo::PendingRemote<mojom::blink::StorageArea> area,
scoped_refptr<base::SingleThreadTaskRunner> ipc_runner, scoped_refptr<base::SingleThreadTaskRunner> ipc_runner,
InspectorEventListener* listener); StorageNamespace* storage_namespace);
CachedStorageArea( CachedStorageArea(
scoped_refptr<const SecurityOrigin> origin, scoped_refptr<const SecurityOrigin> origin,
mojo::PendingAssociatedRemote<mojom::blink::StorageArea> area, mojo::PendingAssociatedRemote<mojom::blink::StorageArea> area,
scoped_refptr<base::SingleThreadTaskRunner> ipc_runner, scoped_refptr<base::SingleThreadTaskRunner> ipc_runner,
InspectorEventListener* listener); StorageNamespace* storage_namespace);
friend class RefCounted<CachedStorageArea>; friend class RefCounted<CachedStorageArea>;
~CachedStorageArea() override; ~CachedStorageArea() override;
...@@ -180,7 +171,7 @@ class MODULES_EXPORT CachedStorageArea ...@@ -180,7 +171,7 @@ class MODULES_EXPORT CachedStorageArea
FormatOption format_option); FormatOption format_option);
const scoped_refptr<const SecurityOrigin> origin_; const scoped_refptr<const SecurityOrigin> origin_;
InspectorEventListener* const inspector_event_listener_; const WeakPersistent<StorageNamespace> storage_namespace_;
const scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner_; const scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner_;
std::unique_ptr<StorageAreaMap> map_; std::unique_ptr<StorageAreaMap> map_;
......
...@@ -16,8 +16,7 @@ namespace blink { ...@@ -16,8 +16,7 @@ namespace blink {
using FormatOption = CachedStorageArea::FormatOption; using FormatOption = CachedStorageArea::FormatOption;
class CachedStorageAreaTest : public testing::Test, class CachedStorageAreaTest : public testing::Test {
public CachedStorageArea::InspectorEventListener {
public: public:
const scoped_refptr<SecurityOrigin> kOrigin = const scoped_refptr<SecurityOrigin> kOrigin =
SecurityOrigin::CreateFromString("http://dom_storage/"); SecurityOrigin::CreateFromString("http://dom_storage/");
...@@ -33,11 +32,11 @@ class CachedStorageAreaTest : public testing::Test, ...@@ -33,11 +32,11 @@ class CachedStorageAreaTest : public testing::Test,
if (IsSessionStorage()) { if (IsSessionStorage()) {
cached_area_ = CachedStorageArea::CreateForSessionStorage( cached_area_ = CachedStorageArea::CreateForSessionStorage(
kOrigin, mock_storage_area_.GetAssociatedInterfaceRemote(), kOrigin, mock_storage_area_.GetAssociatedInterfaceRemote(),
scheduler::GetSingleThreadTaskRunnerForTesting(), this); scheduler::GetSingleThreadTaskRunnerForTesting(), nullptr);
} else { } else {
cached_area_ = CachedStorageArea::CreateForLocalStorage( cached_area_ = CachedStorageArea::CreateForLocalStorage(
kOrigin, mock_storage_area_.GetInterfaceRemote(), kOrigin, mock_storage_area_.GetInterfaceRemote(),
scheduler::GetSingleThreadTaskRunnerForTesting(), this); scheduler::GetSingleThreadTaskRunnerForTesting(), nullptr);
} }
source_area_ = MakeGarbageCollected<FakeAreaSource>(kPageUrl); source_area_ = MakeGarbageCollected<FakeAreaSource>(kPageUrl);
source_area_id_ = cached_area_->RegisterSource(source_area_); source_area_id_ = cached_area_->RegisterSource(source_area_);
...@@ -46,11 +45,6 @@ class CachedStorageAreaTest : public testing::Test, ...@@ -46,11 +45,6 @@ class CachedStorageAreaTest : public testing::Test,
cached_area_->RegisterSource(source_area2_); cached_area_->RegisterSource(source_area2_);
} }
void DidDispatchStorageEvent(const SecurityOrigin* origin,
const String& key,
const String& old_value,
const String& new_value) override {}
virtual bool IsSessionStorage() { return false; } virtual bool IsSessionStorage() { return false; }
bool IsCacheLoaded() { return cached_area_->map_.get(); } bool IsCacheLoaded() { return cached_area_->map_.get(); }
......
...@@ -52,8 +52,6 @@ StorageNamespace::StorageNamespace(StorageController* controller, ...@@ -52,8 +52,6 @@ StorageNamespace::StorageNamespace(StorageController* controller,
const String& namespace_id) const String& namespace_id)
: controller_(controller), namespace_id_(namespace_id) {} : controller_(controller), namespace_id_(namespace_id) {}
StorageNamespace::~StorageNamespace() = default;
// static // static
void StorageNamespace::ProvideSessionStorageNamespaceTo(Page& page, void StorageNamespace::ProvideSessionStorageNamespaceTo(Page& page,
WebViewClient* client) { WebViewClient* client) {
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom-blink-forward.h" #include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/storage/cached_storage_area.h"
#include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h" #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/supplementable.h" #include "third_party/blink/renderer/platform/supplementable.h"
...@@ -44,6 +43,7 @@ ...@@ -44,6 +43,7 @@
namespace blink { namespace blink {
class CachedStorageArea;
class InspectorDOMStorageAgent; class InspectorDOMStorageAgent;
class StorageController; class StorageController;
class SecurityOrigin; class SecurityOrigin;
...@@ -66,8 +66,7 @@ class WebViewClient; ...@@ -66,8 +66,7 @@ class WebViewClient;
// is used to get the storage area for an origin. // is used to get the storage area for an origin.
class MODULES_EXPORT StorageNamespace final class MODULES_EXPORT StorageNamespace final
: public GarbageCollected<StorageNamespace>, : public GarbageCollected<StorageNamespace>,
public Supplement<Page>, public Supplement<Page> {
public CachedStorageArea::InspectorEventListener {
USING_GARBAGE_COLLECTED_MIXIN(StorageNamespace); USING_GARBAGE_COLLECTED_MIXIN(StorageNamespace);
public: public:
...@@ -83,8 +82,6 @@ class MODULES_EXPORT StorageNamespace final ...@@ -83,8 +82,6 @@ class MODULES_EXPORT StorageNamespace final
// Creates a namespace for SessionStorage. // Creates a namespace for SessionStorage.
StorageNamespace(StorageController*, const String& namespace_id); StorageNamespace(StorageController*, const String& namespace_id);
~StorageNamespace() override;
scoped_refptr<CachedStorageArea> GetCachedArea(const SecurityOrigin* origin); scoped_refptr<CachedStorageArea> GetCachedArea(const SecurityOrigin* origin);
// Only valid to call this if |this| and |target| are session storage // Only valid to call this if |this| and |target| are session storage
...@@ -108,7 +105,7 @@ class MODULES_EXPORT StorageNamespace final ...@@ -108,7 +105,7 @@ class MODULES_EXPORT StorageNamespace final
void DidDispatchStorageEvent(const SecurityOrigin* origin, void DidDispatchStorageEvent(const SecurityOrigin* origin,
const String& key, const String& key,
const String& old_value, const String& old_value,
const String& new_value) override; const String& new_value);
private: private:
void EnsureConnected(); void EnsureConnected();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment