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

Side by Side Diff: google_apis/gcm/engine/gcm_store_impl.cc

Issue 138053006: [GCM] Fix use after free memory issue in gcm store (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 11 months 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "google_apis/gcm/engine/gcm_store_impl.h" 5 #include "google_apis/gcm/engine/gcm_store_impl.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/file_util.h" 10 #include "base/file_util.h"
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 } 72 }
73 73
74 std::string ParseOutgoingKey(const std::string& key) { 74 std::string ParseOutgoingKey(const std::string& key) {
75 return key.substr(arraysize(kOutgoingMsgKeyStart) - 1); 75 return key.substr(arraysize(kOutgoingMsgKeyStart) - 1);
76 } 76 }
77 77
78 std::string ParseUsername(const std::string& key) { 78 std::string ParseUsername(const std::string& key) {
79 return key.substr(arraysize(kUserSerialNumberKeyStart) - 1); 79 return key.substr(arraysize(kUserSerialNumberKeyStart) - 1);
80 } 80 }
81 81
82 // Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore
83 // outlive the slice.
84 // For example: MakeSlice(MakeOutgoingKey(x)) is invalid.
82 leveldb::Slice MakeSlice(const base::StringPiece& s) { 85 leveldb::Slice MakeSlice(const base::StringPiece& s) {
83 return leveldb::Slice(s.begin(), s.size()); 86 return leveldb::Slice(s.begin(), s.size());
84 } 87 }
85 88
86 } // namespace 89 } // namespace
87 90
88 class GCMStoreImpl::Backend 91 class GCMStoreImpl::Backend
89 : public base::RefCountedThreadSafe<GCMStoreImpl::Backend> { 92 : public base::RefCountedThreadSafe<GCMStoreImpl::Backend> {
90 public: 93 public:
91 Backend(const base::FilePath& path, 94 Backend(const base::FilePath& path,
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 228 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
226 return; 229 return;
227 } 230 }
228 231
229 leveldb::WriteOptions write_options; 232 leveldb::WriteOptions write_options;
230 write_options.sync = true; 233 write_options.sync = true;
231 234
232 std::string encrypted_token; 235 std::string encrypted_token;
233 Encryptor::EncryptString(base::Uint64ToString(device_security_token), 236 Encryptor::EncryptString(base::Uint64ToString(device_security_token),
234 &encrypted_token); 237 &encrypted_token);
238 std::string android_id_str = base::Uint64ToString(device_android_id);
235 leveldb::Status s = 239 leveldb::Status s =
236 db_->Put(write_options, 240 db_->Put(write_options,
237 MakeSlice(kDeviceAIDKey), 241 MakeSlice(kDeviceAIDKey),
238 MakeSlice(base::Uint64ToString(device_android_id))); 242 MakeSlice(android_id_str));
239 if (s.ok()) { 243 if (s.ok()) {
240 s = db_->Put( 244 s = db_->Put(
241 write_options, MakeSlice(kDeviceTokenKey), MakeSlice(encrypted_token)); 245 write_options, MakeSlice(kDeviceTokenKey), MakeSlice(encrypted_token));
242 } 246 }
243 if (s.ok()) { 247 if (s.ok()) {
244 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 248 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true));
245 return; 249 return;
246 } 250 }
247 LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 251 LOG(ERROR) << "LevelDB put failed: " << s.ToString();
248 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 252 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
249 } 253 }
250 254
251 void GCMStoreImpl::Backend::AddIncomingMessage(const std::string& persistent_id, 255 void GCMStoreImpl::Backend::AddIncomingMessage(const std::string& persistent_id,
252 const UpdateCallback& callback) { 256 const UpdateCallback& callback) {
253 DVLOG(1) << "Saving incoming message with id " << persistent_id; 257 DVLOG(1) << "Saving incoming message with id " << persistent_id;
254 if (!db_.get()) { 258 if (!db_.get()) {
255 LOG(ERROR) << "GCMStore db doesn't exist."; 259 LOG(ERROR) << "GCMStore db doesn't exist.";
256 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 260 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
257 return; 261 return;
258 } 262 }
259 263
260 leveldb::WriteOptions write_options; 264 leveldb::WriteOptions write_options;
261 write_options.sync = true; 265 write_options.sync = true;
262 266
267 std::string key = MakeIncomingKey(persistent_id);
263 const leveldb::Status s = db_->Put(write_options, 268 const leveldb::Status s = db_->Put(write_options,
264 MakeSlice(MakeIncomingKey(persistent_id)), 269 MakeSlice(key),
265 MakeSlice(persistent_id)); 270 MakeSlice(persistent_id));
266 if (s.ok()) { 271 if (s.ok()) {
267 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 272 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true));
268 return; 273 return;
269 } 274 }
270 LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 275 LOG(ERROR) << "LevelDB put failed: " << s.ToString();
271 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 276 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
272 } 277 }
273 278
274 void GCMStoreImpl::Backend::RemoveIncomingMessages( 279 void GCMStoreImpl::Backend::RemoveIncomingMessages(
275 const PersistentIdList& persistent_ids, 280 const PersistentIdList& persistent_ids,
276 const UpdateCallback& callback) { 281 const UpdateCallback& callback) {
277 if (!db_.get()) { 282 if (!db_.get()) {
278 LOG(ERROR) << "GCMStore db doesn't exist."; 283 LOG(ERROR) << "GCMStore db doesn't exist.";
279 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 284 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
280 return; 285 return;
281 } 286 }
282 leveldb::WriteOptions write_options; 287 leveldb::WriteOptions write_options;
283 write_options.sync = true; 288 write_options.sync = true;
284 289
285 leveldb::Status s; 290 leveldb::Status s;
286 for (PersistentIdList::const_iterator iter = persistent_ids.begin(); 291 for (PersistentIdList::const_iterator iter = persistent_ids.begin();
287 iter != persistent_ids.end(); 292 iter != persistent_ids.end();
288 ++iter) { 293 ++iter) {
289 DVLOG(1) << "Removing incoming message with id " << *iter; 294 DVLOG(1) << "Removing incoming message with id " << *iter;
290 s = db_->Delete(write_options, MakeSlice(MakeIncomingKey(*iter))); 295 std::string key = MakeIncomingKey(*iter);
296 s = db_->Delete(write_options, MakeSlice(key));
291 if (!s.ok()) 297 if (!s.ok())
292 break; 298 break;
293 } 299 }
294 if (s.ok()) { 300 if (s.ok()) {
295 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 301 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true));
296 return; 302 return;
297 } 303 }
298 LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); 304 LOG(ERROR) << "LevelDB remove failed: " << s.ToString();
299 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 305 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
300 } 306 }
301 307
302 void GCMStoreImpl::Backend::AddOutgoingMessage(const std::string& persistent_id, 308 void GCMStoreImpl::Backend::AddOutgoingMessage(const std::string& persistent_id,
303 const MCSMessage& message, 309 const MCSMessage& message,
304 const UpdateCallback& callback) { 310 const UpdateCallback& callback) {
305 DVLOG(1) << "Saving outgoing message with id " << persistent_id; 311 DVLOG(1) << "Saving outgoing message with id " << persistent_id;
306 if (!db_.get()) { 312 if (!db_.get()) {
307 LOG(ERROR) << "GCMStore db doesn't exist."; 313 LOG(ERROR) << "GCMStore db doesn't exist.";
308 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 314 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
309 return; 315 return;
310 } 316 }
311 leveldb::WriteOptions write_options; 317 leveldb::WriteOptions write_options;
312 write_options.sync = true; 318 write_options.sync = true;
313 319
314 std::string data = 320 std::string data =
315 static_cast<char>(message.tag()) + message.SerializeAsString(); 321 static_cast<char>(message.tag()) + message.SerializeAsString();
322 std::string key = MakeOutgoingKey(persistent_id);
316 const leveldb::Status s = db_->Put(write_options, 323 const leveldb::Status s = db_->Put(write_options,
317 MakeSlice(MakeOutgoingKey(persistent_id)), 324 MakeSlice(key),
318 MakeSlice(data)); 325 MakeSlice(data));
319 if (s.ok()) { 326 if (s.ok()) {
320 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 327 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true));
321 return; 328 return;
322 } 329 }
323 LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 330 LOG(ERROR) << "LevelDB put failed: " << s.ToString();
324 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 331 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
325 } 332 }
326 333
327 void GCMStoreImpl::Backend::RemoveOutgoingMessages( 334 void GCMStoreImpl::Backend::RemoveOutgoingMessages(
(...skipping 13 matching lines...) Expand all
341 write_options.sync = true; 348 write_options.sync = true;
342 349
343 AppIdToMessageCountMap removed_message_counts; 350 AppIdToMessageCountMap removed_message_counts;
344 351
345 leveldb::Status s; 352 leveldb::Status s;
346 for (PersistentIdList::const_iterator iter = persistent_ids.begin(); 353 for (PersistentIdList::const_iterator iter = persistent_ids.begin();
347 iter != persistent_ids.end(); 354 iter != persistent_ids.end();
348 ++iter) { 355 ++iter) {
349 DVLOG(1) << "Removing outgoing message with id " << *iter; 356 DVLOG(1) << "Removing outgoing message with id " << *iter;
350 std::string outgoing_message; 357 std::string outgoing_message;
351 leveldb::Slice key_slice = MakeSlice(MakeOutgoingKey(*iter)); 358 std::string key = MakeOutgoingKey(*iter);
352 s = db_->Get(read_options, key_slice, &outgoing_message); 359 s = db_->Get(read_options,
360 MakeSlice(key),
361 &outgoing_message);
353 if (!s.ok()) 362 if (!s.ok())
354 break; 363 break;
355 mcs_proto::DataMessageStanza data_message; 364 mcs_proto::DataMessageStanza data_message;
356 // Skip the initial tag byte and parse the rest to extract the message. 365 // Skip the initial tag byte and parse the rest to extract the message.
357 if (data_message.ParseFromString(outgoing_message.substr(1))) { 366 if (data_message.ParseFromString(outgoing_message.substr(1))) {
358 DCHECK(!data_message.from().empty()); 367 DCHECK(!data_message.from().empty());
359 if (removed_message_counts.count(data_message.from()) != 0) 368 if (removed_message_counts.count(data_message.from()) != 0)
360 removed_message_counts[data_message.from()]++; 369 removed_message_counts[data_message.from()]++;
361 else 370 else
362 removed_message_counts[data_message.from()] = 1; 371 removed_message_counts[data_message.from()] = 1;
363 } 372 }
364 DVLOG(1) << "Removing outgoing message with id " << *iter; 373 DVLOG(1) << "Removing outgoing message with id " << *iter;
365 // Have to create a new slice to perform the deletion. 374 s = db_->Delete(write_options, MakeSlice(key));
366 s = db_->Delete(write_options, MakeSlice(MakeOutgoingKey(*iter)));
367 if (!s.ok()) 375 if (!s.ok())
368 break; 376 break;
369 } 377 }
370 if (s.ok()) { 378 if (s.ok()) {
371 foreground_task_runner_->PostTask(FROM_HERE, 379 foreground_task_runner_->PostTask(FROM_HERE,
372 base::Bind(callback, 380 base::Bind(callback,
373 true, 381 true,
374 removed_message_counts)); 382 removed_message_counts));
375 return; 383 return;
376 } 384 }
(...skipping 10 matching lines...) Expand all
387 const UpdateCallback& callback) { 395 const UpdateCallback& callback) {
388 DVLOG(1) << "Saving username to serial number mapping for user: " << username; 396 DVLOG(1) << "Saving username to serial number mapping for user: " << username;
389 if (!db_.get()) { 397 if (!db_.get()) {
390 LOG(ERROR) << "GCMStore db doesn't exist."; 398 LOG(ERROR) << "GCMStore db doesn't exist.";
391 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 399 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
392 return; 400 return;
393 } 401 }
394 leveldb::WriteOptions write_options; 402 leveldb::WriteOptions write_options;
395 write_options.sync = true; 403 write_options.sync = true;
396 404
405 std::string key = MakeUserSerialNumberKey(username);
406 std::string serial_number_str = base::Int64ToString(serial_number);
397 const leveldb::Status status = 407 const leveldb::Status status =
398 db_->Put(write_options, 408 db_->Put(write_options,
399 MakeSlice(MakeUserSerialNumberKey(username)), 409 MakeSlice(key),
400 MakeSlice(base::Int64ToString(serial_number))); 410 MakeSlice(serial_number_str));
401 if (status.ok()) { 411 if (status.ok()) {
402 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 412 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true));
403 return; 413 return;
404 } 414 }
405 LOG(ERROR) << "LevelDB put failed: " << status.ToString(); 415 LOG(ERROR) << "LevelDB put failed: " << status.ToString();
406 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 416 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
407 } 417 }
408 418
409 void GCMStoreImpl::Backend::RemoveUserSerialNumber( 419 void GCMStoreImpl::Backend::RemoveUserSerialNumber(
410 const std::string& username, 420 const std::string& username,
(...skipping 21 matching lines...) Expand all
432 DVLOG(1) << "Updating the value of next user serial number to: " 442 DVLOG(1) << "Updating the value of next user serial number to: "
433 << next_serial_number; 443 << next_serial_number;
434 if (!db_.get()) { 444 if (!db_.get()) {
435 LOG(ERROR) << "GCMStore db doesn't exist."; 445 LOG(ERROR) << "GCMStore db doesn't exist.";
436 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 446 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
437 return; 447 return;
438 } 448 }
439 leveldb::WriteOptions write_options; 449 leveldb::WriteOptions write_options;
440 write_options.sync = true; 450 write_options.sync = true;
441 451
452 std::string serial_number_str = base::Int64ToString(next_serial_number);
442 const leveldb::Status status = 453 const leveldb::Status status =
443 db_->Put(write_options, 454 db_->Put(write_options,
444 MakeSlice(kNextSerialNumberKey), 455 MakeSlice(kNextSerialNumberKey),
445 MakeSlice(base::Int64ToString(next_serial_number))); 456 MakeSlice(serial_number_str));
446 if (status.ok()) { 457 if (status.ok()) {
447 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 458 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true));
448 return; 459 return;
449 } 460 }
450 LOG(ERROR) << "LevelDB put failed: " << status.ToString(); 461 LOG(ERROR) << "LevelDB put failed: " << status.ToString();
451 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 462 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
452 } 463 }
453 464
454 bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id, 465 bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id,
455 uint64* security_token) { 466 uint64* security_token) {
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 removed_message_counts.begin(); 800 removed_message_counts.begin();
790 iter != removed_message_counts.end(); ++iter) { 801 iter != removed_message_counts.end(); ++iter) {
791 DCHECK_NE(app_message_counts_.count(iter->first), 0U); 802 DCHECK_NE(app_message_counts_.count(iter->first), 0U);
792 app_message_counts_[iter->first] -= iter->second; 803 app_message_counts_[iter->first] -= iter->second;
793 DCHECK_GE(app_message_counts_[iter->first], 0); 804 DCHECK_GE(app_message_counts_[iter->first], 0);
794 } 805 }
795 callback.Run(true); 806 callback.Run(true);
796 } 807 }
797 808
798 } // namespace gcm 809 } // namespace gcm
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698