Commit 6b04ff4e authored by Ken Rockot's avatar Ken Rockot Committed by Chromium LUCI CQ

Fix UAF in Local Storage shutdown

This ensures that dangling AsyncDomStorageDatabase references are
properly cleaned up when the database is freed during LocalStorageImpl
shutdown, preventing UAFs in potentially already-scheduled tasks which
would otherwise attempt to use those references.

Fixed: 1152800
Change-Id: Ic98a00d4605aed61f3dee4a2cb9b0c14f3ebf868
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2565711
Auto-Submit: Ken Rockot <rockot@google.com>
Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
Commit-Queue: Ken Rockot <rockot@google.com>
Cr-Commit-Position: refs/heads/master@{#832146}
parent 1eee18ab
......@@ -796,6 +796,12 @@ void LocalStorageImpl::RunWhenConnected(base::OnceClosure callback) {
std::move(callback).Run();
}
void LocalStorageImpl::PurgeAllStorageAreas() {
for (const auto& it : areas_)
it.second->storage_area()->CancelAllPendingRequests();
areas_.clear();
}
void LocalStorageImpl::InitiateConnection(bool in_memory_only) {
if (connection_state_ == CONNECTION_SHUTDOWN)
return;
......@@ -922,9 +928,7 @@ void LocalStorageImpl::DeleteAndRecreateDatabase(const char* histogram_name) {
// We're about to set database_ to null, so delete the StorageAreaImpls
// that might still be using the old database.
for (const auto& it : areas_)
it.second->storage_area()->CancelAllPendingRequests();
areas_.clear();
PurgeAllStorageAreas();
// Reset state to be in process of connecting. This will cause requests for
// StorageAreas to be queued until the connection is complete.
......@@ -1100,6 +1104,7 @@ void LocalStorageImpl::OnShutdownComplete() {
// Flush any final tasks on the DB task runner before invoking the callback.
leveldb_task_runner_->PostTaskAndReply(
FROM_HERE, base::DoNothing(), std::move(shutdown_complete_callback_));
PurgeAllStorageAreas();
database_.reset();
}
......
......@@ -112,6 +112,10 @@ class LocalStorageImpl : public base::trace_event::MemoryDumpProvider,
// Initiates connecting to the database if no connection is in progres yet.
void RunWhenConnected(base::OnceClosure callback);
// StorageAreas held by this LocalStorageImpl retain an unmanaged reference to
// `database_`. This deletes them and is used any time `database_` is reset.
void PurgeAllStorageAreas();
// Part of our asynchronous directory opening called from RunWhenConnected().
void InitiateConnection(bool in_memory_only = false);
void OnDatabaseOpened(leveldb::Status status);
......
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