Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(319)

Side by Side Diff: content/browser/indexed_db/indexed_db_dispatcher_host.cc

Issue 774593004: IndexedDB: Fixed cursor/blob use-after-free bug (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Ensuring AckReceivedBlobs called on IO thread Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/browser/indexed_db/indexed_db_dispatcher_host.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/indexed_db/indexed_db_dispatcher_host.h" 5 #include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/guid.h"
10 #include "base/memory/scoped_vector.h" 11 #include "base/memory/scoped_vector.h"
11 #include "base/process/process.h" 12 #include "base/process/process.h"
12 #include "base/stl_util.h" 13 #include "base/stl_util.h"
13 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
14 #include "content/browser/child_process_security_policy_impl.h" 15 #include "content/browser/child_process_security_policy_impl.h"
15 #include "content/browser/indexed_db/indexed_db_callbacks.h" 16 #include "content/browser/indexed_db/indexed_db_callbacks.h"
16 #include "content/browser/indexed_db/indexed_db_connection.h" 17 #include "content/browser/indexed_db/indexed_db_connection.h"
17 #include "content/browser/indexed_db/indexed_db_context_impl.h" 18 #include "content/browser/indexed_db/indexed_db_context_impl.h"
18 #include "content/browser/indexed_db/indexed_db_cursor.h" 19 #include "content/browser/indexed_db/indexed_db_cursor.h"
19 #include "content/browser/indexed_db/indexed_db_database_callbacks.h" 20 #include "content/browser/indexed_db/indexed_db_database_callbacks.h"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 request_context_(request_context), 63 request_context_(request_context),
63 indexed_db_context_(indexed_db_context), 64 indexed_db_context_(indexed_db_context),
64 blob_storage_context_(blob_storage_context), 65 blob_storage_context_(blob_storage_context),
65 database_dispatcher_host_(new DatabaseDispatcherHost(this)), 66 database_dispatcher_host_(new DatabaseDispatcherHost(this)),
66 cursor_dispatcher_host_(new CursorDispatcherHost(this)), 67 cursor_dispatcher_host_(new CursorDispatcherHost(this)),
67 ipc_process_id_(ipc_process_id) { 68 ipc_process_id_(ipc_process_id) {
68 DCHECK(indexed_db_context_.get()); 69 DCHECK(indexed_db_context_.get());
69 } 70 }
70 71
71 IndexedDBDispatcherHost::~IndexedDBDispatcherHost() { 72 IndexedDBDispatcherHost::~IndexedDBDispatcherHost() {
72 STLDeleteValues(&blob_data_handle_map_); 73 for (auto& iter : blob_data_handle_map_)
74 delete iter.second.first;
73 } 75 }
74 76
75 void IndexedDBDispatcherHost::OnChannelConnected(int32 peer_pid) { 77 void IndexedDBDispatcherHost::OnChannelConnected(int32 peer_pid) {
76 BrowserMessageFilter::OnChannelConnected(peer_pid); 78 BrowserMessageFilter::OnChannelConnected(peer_pid);
77 79
78 if (request_context_getter_.get()) { 80 if (request_context_getter_.get()) {
79 DCHECK(!request_context_); 81 DCHECK(!request_context_);
80 request_context_ = request_context_getter_->GetURLRequestContext(); 82 request_context_ = request_context_getter_->GetURLRequestContext();
81 request_context_getter_ = NULL; 83 request_context_getter_ = NULL;
82 DCHECK(request_context_); 84 DCHECK(request_context_);
(...skipping 28 matching lines...) Expand all
111 // Note that we explicitly separate CloseAll() from destruction of the 113 // Note that we explicitly separate CloseAll() from destruction of the
112 // DatabaseDispatcherHost, since CloseAll() can invoke callbacks which need to 114 // DatabaseDispatcherHost, since CloseAll() can invoke callbacks which need to
113 // be dispatched through database_dispatcher_host_. 115 // be dispatched through database_dispatcher_host_.
114 database_dispatcher_host_->CloseAll(); 116 database_dispatcher_host_->CloseAll();
115 database_dispatcher_host_.reset(); 117 database_dispatcher_host_.reset();
116 cursor_dispatcher_host_.reset(); 118 cursor_dispatcher_host_.reset();
117 } 119 }
118 120
119 base::TaskRunner* IndexedDBDispatcherHost::OverrideTaskRunnerForMessage( 121 base::TaskRunner* IndexedDBDispatcherHost::OverrideTaskRunnerForMessage(
120 const IPC::Message& message) { 122 const IPC::Message& message) {
121 if (IPC_MESSAGE_CLASS(message) == IndexedDBMsgStart && 123 if (IPC_MESSAGE_CLASS(message) != IndexedDBMsgStart)
122 message.type() != IndexedDBHostMsg_DatabasePut::ID) 124 return NULL;
123 return indexed_db_context_->TaskRunner(); 125
124 return NULL; 126 switch (message.type()) {
127 case IndexedDBHostMsg_DatabasePut::ID:
128 case IndexedDBHostMsg_AckReceivedBlobs::ID:
129 return NULL;
130 default:
131 return indexed_db_context_->TaskRunner();
132 }
125 } 133 }
126 134
127 bool IndexedDBDispatcherHost::OnMessageReceived(const IPC::Message& message) { 135 bool IndexedDBDispatcherHost::OnMessageReceived(const IPC::Message& message) {
128 if (IPC_MESSAGE_CLASS(message) != IndexedDBMsgStart) 136 if (IPC_MESSAGE_CLASS(message) != IndexedDBMsgStart)
129 return false; 137 return false;
130 138
131 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread() || 139 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread() ||
132 message.type() == IndexedDBHostMsg_DatabasePut::ID); 140 (message.type() == IndexedDBHostMsg_DatabasePut::ID ||
141 message.type() == IndexedDBHostMsg_AckReceivedBlobs::ID));
133 142
134 bool handled = database_dispatcher_host_->OnMessageReceived(message) || 143 bool handled = database_dispatcher_host_->OnMessageReceived(message) ||
135 cursor_dispatcher_host_->OnMessageReceived(message); 144 cursor_dispatcher_host_->OnMessageReceived(message);
136 145
137 if (!handled) { 146 if (!handled) {
138 handled = true; 147 handled = true;
139 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcherHost, message) 148 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcherHost, message)
140 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryGetDatabaseNames, 149 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryGetDatabaseNames,
141 OnIDBFactoryGetDatabaseNames) 150 OnIDBFactoryGetDatabaseNames)
142 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryOpen, OnIDBFactoryOpen) 151 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryOpen, OnIDBFactoryOpen)
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 int64 host_transaction_id) { 211 int64 host_transaction_id) {
203 return host_transaction_id & 0xffffffff; 212 return host_transaction_id & 0xffffffff;
204 } 213 }
205 214
206 // static 215 // static
207 uint32 IndexedDBDispatcherHost::TransactionIdToProcessId( 216 uint32 IndexedDBDispatcherHost::TransactionIdToProcessId(
208 int64 host_transaction_id) { 217 int64 host_transaction_id) {
209 return (host_transaction_id >> 32) & 0xffffffff; 218 return (host_transaction_id >> 32) & 0xffffffff;
210 } 219 }
211 220
212 void IndexedDBDispatcherHost::HoldBlobDataHandle( 221 std::string IndexedDBDispatcherHost::HoldBlobData(
213 const std::string& uuid, 222 const IndexedDBBlobInfo& blob_info) {
214 scoped_ptr<storage::BlobDataHandle> blob_data_handle) { 223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
224 std::string uuid = blob_info.uuid();
225 storage::BlobStorageContext* context = blob_storage_context_->context();
226 scoped_ptr<storage::BlobDataHandle> blob_data_handle;
227 if (uuid.empty()) {
228 uuid = base::GenerateGUID();
229 scoped_refptr<storage::BlobData> blob_data = new storage::BlobData(uuid);
230 blob_data->set_content_type(base::UTF16ToUTF8(blob_info.type()));
231 blob_data->AppendFile(blob_info.file_path(), 0, blob_info.size(),
232 blob_info.last_modified());
233 blob_data_handle = context->AddFinishedBlob(blob_data.get());
234 } else {
235 auto iter = blob_data_handle_map_.find(uuid);
236 if (iter != blob_data_handle_map_.end()) {
237 iter->second.second += 1;
238 return uuid;
239 }
240 blob_data_handle = context->GetBlobDataFromUUID(uuid);
241 }
242
215 DCHECK(!ContainsKey(blob_data_handle_map_, uuid)); 243 DCHECK(!ContainsKey(blob_data_handle_map_, uuid));
216 blob_data_handle_map_[uuid] = blob_data_handle.release(); 244 blob_data_handle_map_[uuid] =
245 std::pair<storage::BlobDataHandle*, int>(blob_data_handle.release(), 1);
jsbell 2014/12/04 18:13:42 Can you use std::make_pair here?
cmumford 2014/12/04 18:17:52 Done.
246 return uuid;
217 } 247 }
218 248
219 void IndexedDBDispatcherHost::DropBlobDataHandle(const std::string& uuid) { 249 void IndexedDBDispatcherHost::DropBlobData(const std::string& uuid) {
250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
220 BlobDataHandleMap::iterator iter = blob_data_handle_map_.find(uuid); 251 BlobDataHandleMap::iterator iter = blob_data_handle_map_.find(uuid);
221 if (iter != blob_data_handle_map_.end()) { 252 if (iter != blob_data_handle_map_.end()) {
222 delete iter->second; 253 DCHECK_GE(iter->second.second, 1);
223 blob_data_handle_map_.erase(iter); 254 if (iter->second.second == 1) {
255 delete iter->second.first;
256 blob_data_handle_map_.erase(iter);
257 } else {
258 iter->second.second -= 1;
259 }
224 } else { 260 } else {
225 DLOG(FATAL) << "Failed to find blob UUID in map:" << uuid; 261 DLOG(FATAL) << "Failed to find blob UUID in map:" << uuid;
226 } 262 }
227 } 263 }
228 264
229 IndexedDBCursor* IndexedDBDispatcherHost::GetCursorFromId(int32 ipc_cursor_id) { 265 IndexedDBCursor* IndexedDBDispatcherHost::GetCursorFromId(int32 ipc_cursor_id) {
230 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); 266 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
231 return cursor_dispatcher_host_->map_.Lookup(ipc_cursor_id); 267 return cursor_dispatcher_host_->map_.Lookup(ipc_cursor_id);
232 } 268 }
233 269
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 // OnPutHelper exists only to allow us to hop threads while holding a reference 371 // OnPutHelper exists only to allow us to hop threads while holding a reference
336 // to the IndexedDBDispatcherHost. 372 // to the IndexedDBDispatcherHost.
337 void IndexedDBDispatcherHost::OnPutHelper( 373 void IndexedDBDispatcherHost::OnPutHelper(
338 const IndexedDBHostMsg_DatabasePut_Params& params, 374 const IndexedDBHostMsg_DatabasePut_Params& params,
339 std::vector<storage::BlobDataHandle*> handles) { 375 std::vector<storage::BlobDataHandle*> handles) {
340 database_dispatcher_host_->OnPut(params, handles); 376 database_dispatcher_host_->OnPut(params, handles);
341 } 377 }
342 378
343 void IndexedDBDispatcherHost::OnAckReceivedBlobs( 379 void IndexedDBDispatcherHost::OnAckReceivedBlobs(
344 const std::vector<std::string>& uuids) { 380 const std::vector<std::string>& uuids) {
345 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); 381 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
346 for (const auto& uuid : uuids) 382 for (const auto& uuid : uuids)
347 DropBlobDataHandle(uuid); 383 DropBlobData(uuid);
348 } 384 }
349 385
350 void IndexedDBDispatcherHost::FinishTransaction(int64 host_transaction_id, 386 void IndexedDBDispatcherHost::FinishTransaction(int64 host_transaction_id,
351 bool committed) { 387 bool committed) {
352 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); 388 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
353 if (!database_dispatcher_host_) 389 if (!database_dispatcher_host_)
354 return; 390 return;
355 TransactionIDToURLMap& transaction_url_map = 391 TransactionIDToURLMap& transaction_url_map =
356 database_dispatcher_host_->transaction_url_map_; 392 database_dispatcher_host_->transaction_url_map_;
357 TransactionIDToSizeMap& transaction_size_map = 393 TransactionIDToSizeMap& transaction_size_map =
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 IndexedDBConnection* connection = map_.Lookup(iter.first); 482 IndexedDBConnection* connection = map_.Lookup(iter.first);
447 if (connection && connection->IsConnected()) { 483 if (connection && connection->IsConnected()) {
448 connection->Close(); 484 connection->Close();
449 parent_->Context()->ConnectionClosed(iter.second, connection); 485 parent_->Context()->ConnectionClosed(iter.second, connection);
450 } 486 }
451 } 487 }
452 } 488 }
453 489
454 bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived( 490 bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived(
455 const IPC::Message& message) { 491 const IPC::Message& message) {
456
457 DCHECK( 492 DCHECK(
458 (message.type() == IndexedDBHostMsg_DatabasePut::ID) || 493 (message.type() == IndexedDBHostMsg_DatabasePut::ID ||
494 message.type() == IndexedDBHostMsg_AckReceivedBlobs::ID) ||
459 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); 495 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
460 496
461 bool handled = true; 497 bool handled = true;
462 IPC_BEGIN_MESSAGE_MAP( 498 IPC_BEGIN_MESSAGE_MAP(
463 IndexedDBDispatcherHost::DatabaseDispatcherHost, message) 499 IndexedDBDispatcherHost::DatabaseDispatcherHost, message)
464 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateObjectStore, 500 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateObjectStore,
465 OnCreateObjectStore) 501 OnCreateObjectStore)
466 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteObjectStore, 502 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteObjectStore,
467 OnDeleteObjectStore) 503 OnDeleteObjectStore)
468 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateTransaction, 504 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateTransaction,
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 } 1022 }
987 1023
988 void IndexedDBDispatcherHost::CursorDispatcherHost::OnDestroyed( 1024 void IndexedDBDispatcherHost::CursorDispatcherHost::OnDestroyed(
989 int32 ipc_object_id) { 1025 int32 ipc_object_id) {
990 DCHECK( 1026 DCHECK(
991 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); 1027 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
992 parent_->DestroyObject(&map_, ipc_object_id); 1028 parent_->DestroyObject(&map_, ipc_object_id);
993 } 1029 }
994 1030
995 } // namespace content 1031 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/indexed_db/indexed_db_dispatcher_host.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698