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

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: Removed unused BlobStorageContext param from CreateBlobData() 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] = std::make_pair(blob_data_handle.release(), 1);
245 return uuid;
217 } 246 }
218 247
219 void IndexedDBDispatcherHost::DropBlobDataHandle(const std::string& uuid) { 248 void IndexedDBDispatcherHost::DropBlobData(const std::string& uuid) {
249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
220 BlobDataHandleMap::iterator iter = blob_data_handle_map_.find(uuid); 250 BlobDataHandleMap::iterator iter = blob_data_handle_map_.find(uuid);
221 if (iter != blob_data_handle_map_.end()) { 251 if (iter != blob_data_handle_map_.end()) {
222 delete iter->second; 252 DCHECK_GE(iter->second.second, 1);
223 blob_data_handle_map_.erase(iter); 253 if (iter->second.second == 1) {
254 delete iter->second.first;
255 blob_data_handle_map_.erase(iter);
256 } else {
257 iter->second.second -= 1;
258 }
224 } else { 259 } else {
225 DLOG(FATAL) << "Failed to find blob UUID in map:" << uuid; 260 DLOG(FATAL) << "Failed to find blob UUID in map:" << uuid;
226 } 261 }
227 } 262 }
228 263
229 IndexedDBCursor* IndexedDBDispatcherHost::GetCursorFromId(int32 ipc_cursor_id) { 264 IndexedDBCursor* IndexedDBDispatcherHost::GetCursorFromId(int32 ipc_cursor_id) {
230 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); 265 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
231 return cursor_dispatcher_host_->map_.Lookup(ipc_cursor_id); 266 return cursor_dispatcher_host_->map_.Lookup(ipc_cursor_id);
232 } 267 }
233 268
(...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 370 // OnPutHelper exists only to allow us to hop threads while holding a reference
336 // to the IndexedDBDispatcherHost. 371 // to the IndexedDBDispatcherHost.
337 void IndexedDBDispatcherHost::OnPutHelper( 372 void IndexedDBDispatcherHost::OnPutHelper(
338 const IndexedDBHostMsg_DatabasePut_Params& params, 373 const IndexedDBHostMsg_DatabasePut_Params& params,
339 std::vector<storage::BlobDataHandle*> handles) { 374 std::vector<storage::BlobDataHandle*> handles) {
340 database_dispatcher_host_->OnPut(params, handles); 375 database_dispatcher_host_->OnPut(params, handles);
341 } 376 }
342 377
343 void IndexedDBDispatcherHost::OnAckReceivedBlobs( 378 void IndexedDBDispatcherHost::OnAckReceivedBlobs(
344 const std::vector<std::string>& uuids) { 379 const std::vector<std::string>& uuids) {
345 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); 380 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
346 for (const auto& uuid : uuids) 381 for (const auto& uuid : uuids)
347 DropBlobDataHandle(uuid); 382 DropBlobData(uuid);
348 } 383 }
349 384
350 void IndexedDBDispatcherHost::FinishTransaction(int64 host_transaction_id, 385 void IndexedDBDispatcherHost::FinishTransaction(int64 host_transaction_id,
351 bool committed) { 386 bool committed) {
352 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); 387 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
353 if (!database_dispatcher_host_) 388 if (!database_dispatcher_host_)
354 return; 389 return;
355 TransactionIDToURLMap& transaction_url_map = 390 TransactionIDToURLMap& transaction_url_map =
356 database_dispatcher_host_->transaction_url_map_; 391 database_dispatcher_host_->transaction_url_map_;
357 TransactionIDToSizeMap& transaction_size_map = 392 TransactionIDToSizeMap& transaction_size_map =
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 IndexedDBConnection* connection = map_.Lookup(iter.first); 481 IndexedDBConnection* connection = map_.Lookup(iter.first);
447 if (connection && connection->IsConnected()) { 482 if (connection && connection->IsConnected()) {
448 connection->Close(); 483 connection->Close();
449 parent_->Context()->ConnectionClosed(iter.second, connection); 484 parent_->Context()->ConnectionClosed(iter.second, connection);
450 } 485 }
451 } 486 }
452 } 487 }
453 488
454 bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived( 489 bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived(
455 const IPC::Message& message) { 490 const IPC::Message& message) {
456
457 DCHECK( 491 DCHECK(
458 (message.type() == IndexedDBHostMsg_DatabasePut::ID) || 492 (message.type() == IndexedDBHostMsg_DatabasePut::ID ||
493 message.type() == IndexedDBHostMsg_AckReceivedBlobs::ID) ||
459 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); 494 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
460 495
461 bool handled = true; 496 bool handled = true;
462 IPC_BEGIN_MESSAGE_MAP( 497 IPC_BEGIN_MESSAGE_MAP(
463 IndexedDBDispatcherHost::DatabaseDispatcherHost, message) 498 IndexedDBDispatcherHost::DatabaseDispatcherHost, message)
464 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateObjectStore, 499 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateObjectStore,
465 OnCreateObjectStore) 500 OnCreateObjectStore)
466 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteObjectStore, 501 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteObjectStore,
467 OnDeleteObjectStore) 502 OnDeleteObjectStore)
468 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateTransaction, 503 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateTransaction,
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 } 1021 }
987 1022
988 void IndexedDBDispatcherHost::CursorDispatcherHost::OnDestroyed( 1023 void IndexedDBDispatcherHost::CursorDispatcherHost::OnDestroyed(
989 int32 ipc_object_id) { 1024 int32 ipc_object_id) {
990 DCHECK( 1025 DCHECK(
991 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); 1026 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
992 parent_->DestroyObject(&map_, ipc_object_id); 1027 parent_->DestroyObject(&map_, ipc_object_id);
993 } 1028 }
994 1029
995 } // namespace content 1030 } // 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