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

Side by Side Diff: chrome/browser/safe_browsing/safe_browsing_store_file.cc

Issue 10093004: Double-check safe-browsing database validity on update failure. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Check size before reading. Created 8 years, 8 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "chrome/browser/safe_browsing/safe_browsing_store_file.h" 5 #include "chrome/browser/safe_browsing/safe_browsing_store_file.h"
6 6
7 #include "base/md5.h" 7 #include "base/md5.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 9
10 namespace { 10 namespace {
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 // existing file is a SQLite file. Make sure the journal file is 236 // existing file is a SQLite file. Make sure the journal file is
237 // also removed. 237 // also removed.
238 const FilePath journal_filename( 238 const FilePath journal_filename(
239 filename_.value() + FILE_PATH_LITERAL("-journal")); 239 filename_.value() + FILE_PATH_LITERAL("-journal"));
240 if (file_util::PathExists(journal_filename)) 240 if (file_util::PathExists(journal_filename))
241 file_util::Delete(journal_filename, false); 241 file_util::Delete(journal_filename, false);
242 242
243 return true; 243 return true;
244 } 244 }
245 245
246 bool SafeBrowsingStoreFile::CheckValidity() {
247 if (empty_)
248 return true;
249
250 // If the file was not empty, it should be open.
251 DCHECK(file_.get());
252
253 if (!FileRewind(file_.get()))
254 return OnCorruptDatabase();
255
256 int64 size = 0;
257 if (!file_util::GetFileSize(filename_, &size))
258 return OnCorruptDatabase();
259
260 base::MD5Context context;
261 base::MD5Init(&context);
262
263 // Read everything except the final digest.
264 size_t bytes_left = static_cast<size_t>(size);
265 CHECK(size == static_cast<int64>(bytes_left));
266 if (bytes_left < sizeof(base::MD5Digest))
267 return OnCorruptDatabase();
268 bytes_left -= sizeof(base::MD5Digest);
269
270 // Fold the contents of the file into the checksum.
271 while (bytes_left > 0) {
272 char buf[4096];
273 const size_t c = std::min(sizeof(buf), bytes_left);
274 const size_t ret = fread(buf, 1, c, file_.get());
275
276 // The file's size changed while reading, give up.
277 if (ret != c)
278 return OnCorruptDatabase();
279 base::MD5Update(&context, base::StringPiece(buf, c));
280 bytes_left -= c;
281 }
282
283 // Calculate the digest to this point.
284 base::MD5Digest calculated_digest;
285 base::MD5Final(&calculated_digest, &context);
286
287 // Read the stored digest and verify it.
288 base::MD5Digest file_digest;
289 if (!ReadItem(&file_digest, file_.get(), NULL))
290 return OnCorruptDatabase();
291 if (0 != memcmp(&file_digest, &calculated_digest, sizeof(file_digest))) {
292 RecordFormatEvent(FORMAT_EVENT_VALIDITY_CHECKSUM_FAILURE);
293 return OnCorruptDatabase();
294 }
295
296 return true;
297 }
298
246 void SafeBrowsingStoreFile::Init( 299 void SafeBrowsingStoreFile::Init(
247 const FilePath& filename, 300 const FilePath& filename,
248 const base::Closure& corruption_callback 301 const base::Closure& corruption_callback
249 ) { 302 ) {
250 filename_ = filename; 303 filename_ = filename;
251 corruption_callback_ = corruption_callback; 304 corruption_callback_ = corruption_callback;
252 } 305 }
253 306
254 bool SafeBrowsingStoreFile::BeginChunk() { 307 bool SafeBrowsingStoreFile::BeginChunk() {
255 return ClearChunkBuffers(); 308 return ClearChunkBuffers();
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 549
497 // Calculate the digest to this point. 550 // Calculate the digest to this point.
498 base::MD5Digest calculated_digest; 551 base::MD5Digest calculated_digest;
499 base::MD5Final(&calculated_digest, &context); 552 base::MD5Final(&calculated_digest, &context);
500 553
501 // Read the stored checksum and verify it. 554 // Read the stored checksum and verify it.
502 base::MD5Digest file_digest; 555 base::MD5Digest file_digest;
503 if (!ReadItem(&file_digest, file_.get(), NULL)) 556 if (!ReadItem(&file_digest, file_.get(), NULL))
504 return OnCorruptDatabase(); 557 return OnCorruptDatabase();
505 558
506 if (0 != memcmp(&file_digest, &calculated_digest, sizeof(file_digest))) 559 if (0 != memcmp(&file_digest, &calculated_digest, sizeof(file_digest))) {
560 RecordFormatEvent(FORMAT_EVENT_UPDATE_CHECKSUM_FAILURE);
507 return OnCorruptDatabase(); 561 return OnCorruptDatabase();
562 }
508 563
509 // Close the file so we can later rename over it. 564 // Close the file so we can later rename over it.
510 file_.reset(); 565 file_.reset();
511 } 566 }
512 DCHECK(!file_.get()); 567 DCHECK(!file_.get());
513 568
514 // Rewind the temporary storage. 569 // Rewind the temporary storage.
515 if (!FileRewind(new_file_.get())) 570 if (!FileRewind(new_file_.get()))
516 return false; 571 return false;
517 572
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 out->insert(out->end(), sub_chunks_cache_.begin(), sub_chunks_cache_.end()); 749 out->insert(out->end(), sub_chunks_cache_.begin(), sub_chunks_cache_.end());
695 } 750 }
696 751
697 void SafeBrowsingStoreFile::DeleteAddChunk(int32 chunk_id) { 752 void SafeBrowsingStoreFile::DeleteAddChunk(int32 chunk_id) {
698 add_del_cache_.insert(chunk_id); 753 add_del_cache_.insert(chunk_id);
699 } 754 }
700 755
701 void SafeBrowsingStoreFile::DeleteSubChunk(int32 chunk_id) { 756 void SafeBrowsingStoreFile::DeleteSubChunk(int32 chunk_id) {
702 sub_del_cache_.insert(chunk_id); 757 sub_del_cache_.insert(chunk_id);
703 } 758 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698