[go: up one dir, main page]

[IndexedDB] Avoiding UAF in IndexedDBConnection list

The IndexedDBDatabase's connection() list can be modified during a call
to FinishAllTransactions. The AbortAllTransactions method didn't protect
against this, so there was a potential UAF. This patch fixes that.

(cherry picked from commit 6be08e8acbe5eaed18a0b9abeb395de5afa2f1aa)

Bug: 969083
Change-Id: I590e3a6c4f978ee6e582394208fb70cbdd9e5347
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1641625
Commit-Queue: Daniel Murphy <dmurph@chromium.org>
Auto-Submit: Daniel Murphy <dmurph@chromium.org>
Reviewed-by: Chase Phillips <cmp@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#666381}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1654510
Reviewed-by: Victor Costan <pwnall@chromium.org>
Cr-Commit-Position: refs/branch-heads/3809@{#245}
Cr-Branched-From: d82dec1a818f378c464ba307ddd9c92133eac355-refs/heads/master@{#665002}
diff --git a/content/browser/indexed_db/indexed_db_origin_state.cc b/content/browser/indexed_db/indexed_db_origin_state.cc
index 02cb72b..27ad7cf 100644
--- a/content/browser/indexed_db/indexed_db_origin_state.cc
+++ b/content/browser/indexed_db/indexed_db_origin_state.cc
@@ -113,10 +113,21 @@
     auto it = databases_.find(origin);
     if (it == databases_.end())
       continue;
-    for (IndexedDBConnection* connection : it->second->connections()) {
-      connection->FinishAllTransactions(
-          IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionUnknownError,
-                                 "Aborting all transactions for the origin."));
+
+    // Calling FinishAllTransactions can destruct the IndexedDBConnection &
+    // modify the IndexedDBDatabase::connection() list. To prevent UAFs, start
+    // by taking a WeakPtr of all connections, and then iterate that list.
+    std::vector<base::WeakPtr<IndexedDBConnection>> weak_connections;
+    weak_connections.reserve(it->second->connections().size());
+    for (IndexedDBConnection* connection : it->second->connections())
+      weak_connections.push_back(connection->GetWeakPtr());
+
+    for (base::WeakPtr<IndexedDBConnection> connection : weak_connections) {
+      if (connection) {
+        connection->FinishAllTransactions(IndexedDBDatabaseError(
+            blink::kWebIDBDatabaseExceptionUnknownError,
+            "Aborting all transactions for the origin."));
+      }
     }
   }
   if (compact)