Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 #ifndef CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_DATABASE_H_ | 5 #ifndef CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_DATABASE_H_ |
| 6 #define CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_DATABASE_H_ | 6 #define CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_DATABASE_H_ |
| 7 | 7 |
| 8 #include <map> | 8 #include <map> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 360 // A SafeBrowsing whitelist contains a list of whitelisted full-hashes (stored | 360 // A SafeBrowsing whitelist contains a list of whitelisted full-hashes (stored |
| 361 // in a sorted vector) as well as a boolean flag indicating whether all | 361 // in a sorted vector) as well as a boolean flag indicating whether all |
| 362 // lookups in the whitelist should be considered matches for safety. | 362 // lookups in the whitelist should be considered matches for safety. |
| 363 typedef std::pair<std::vector<SBFullHash>, bool> SBWhitelist; | 363 typedef std::pair<std::vector<SBFullHash>, bool> SBWhitelist; |
| 364 | 364 |
| 365 // This map holds a csd malware IP blacklist which maps a prefix mask | 365 // This map holds a csd malware IP blacklist which maps a prefix mask |
| 366 // to a set of hashed blacklisted IP prefixes. Each IP prefix is a hashed | 366 // to a set of hashed blacklisted IP prefixes. Each IP prefix is a hashed |
| 367 // IPv6 IP prefix using SHA-1. | 367 // IPv6 IP prefix using SHA-1. |
| 368 typedef std::map<std::string, base::hash_set<std::string> > IPBlacklist; | 368 typedef std::map<std::string, base::hash_set<std::string> > IPBlacklist; |
| 369 | 369 |
| 370 bool PrefixSetContainsUrl( | 370 typedef std::map<SBPrefix, SBCachedFullHashResult> PrefixGetHashCache; |
| 371 const GURL& url, | 371 |
| 372 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, | 372 // The ThreadSafeStateManager holds the SafeBrowsingDatabase's state which |
| 373 std::vector<SBPrefix>* prefix_hits, | 373 // must be accessed in a thread-safe fashion. It must be constructed on the |
| 374 std::vector<SBFullHashResult>* cache_hits); | 374 // SafeBrowsingDatabaseManager's main thread. The main thread will then be the |
| 375 // only thread on which this state can be modified; allowing for unlocked | |
| 376 // reads on the main thread and thus avoiding contention while performing | |
| 377 // intensive operations such as writing that state to disk. The state can only | |
| 378 // be accessed via (Read|Write)Transactions obtained through this class which | |
| 379 // will automatically handle thread-safety. | |
| 380 class ThreadSafeStateManager { | |
| 381 public: | |
| 382 // Identifiers for stores held by the ThreadSafeStateManager. Allows helper | |
| 383 // methods to start a transaction themselves and keep it as short as | |
| 384 // possible rather than force callers to start the transaction early to pass | |
| 385 // a store pointer to the said helper methods. | |
| 386 enum class SBWhitelistId { | |
| 387 CSD, | |
| 388 DOWNLOAD, | |
| 389 }; | |
| 390 enum class PrefixSetId { | |
| 391 BROWSE, | |
| 392 SIDE_EFFECT_FREE_WHITELIST, | |
| 393 UNWANTED_SOFTWARE, | |
| 394 }; | |
| 395 | |
| 396 // A ReadTransaction allows read-only observations of the | |
| 397 // ThreadSafeStateManager's state. The |prefix_gethash_cache_| has a special | |
| 398 // allowance to be writable from a ReadTransaction but can't benefit from | |
| 399 // unlocked ReadTransactions. ReadTransaction should be held for the | |
| 400 // shortest amount of time possible (e.g., release it before computing final | |
| 401 // results if possible). | |
| 402 class ReadTransaction; | |
| 403 | |
| 404 // A WriteTransaction allows modification of the ThreadSafeStateManager's | |
| 405 // state. It should be used for the shortest amount of time possible (e.g., | |
| 406 // pre-compute the new state before grabbing a WriteTransaction to swap it | |
| 407 // in atomically). | |
| 408 class WriteTransaction; | |
| 409 | |
| 410 ThreadSafeStateManager(); | |
| 411 ~ThreadSafeStateManager(); | |
| 412 | |
| 413 scoped_ptr<ReadTransaction> BeginReadTransaction(); | |
| 414 scoped_ptr<ReadTransaction> BeginReadTransactionNoLockOnMainThread(); | |
| 415 scoped_ptr<WriteTransaction> BeginWriteTransaction(); | |
| 416 | |
| 417 private: | |
| 418 // Used to verify that writes are only made on this object's main thread. | |
| 419 // This is important as this class allows reading from the main thread | |
| 420 // without holding the lock. | |
| 421 base::ThreadChecker thread_checker_; | |
| 422 | |
| 423 // Lock for protecting access to this class' state. | |
| 424 base::Lock lock_; | |
| 425 | |
| 426 SBWhitelist csd_whitelist_; | |
| 427 SBWhitelist download_whitelist_; | |
| 428 | |
| 429 // The IP blacklist should be small. At most a couple hundred IPs. | |
| 430 IPBlacklist ip_blacklist_; | |
| 431 | |
| 432 // PrefixSets to speed up lookups for particularly large lists. The | |
| 433 // PrefixSet themselves are never modified, instead a new one is swapped in | |
| 434 // on update. | |
| 435 scoped_ptr<const safe_browsing::PrefixSet> browse_prefix_set_; | |
| 436 scoped_ptr<const safe_browsing::PrefixSet> | |
| 437 side_effect_free_whitelist_prefix_set_; | |
| 438 scoped_ptr<const safe_browsing::PrefixSet> unwanted_software_prefix_set_; | |
| 439 | |
| 440 // Cache of gethash results for prefix stores. Entries should not be used if | |
| 441 // they are older than their expire_after field. Cached misses will have | |
| 442 // empty full_hashes field. Cleared on each update. | |
| 443 PrefixGetHashCache prefix_gethash_cache_; | |
| 444 | |
| 445 DISALLOW_COPY_AND_ASSIGN(ThreadSafeStateManager); | |
| 446 }; | |
| 447 | |
| 448 // Forward the above inner-definitions to alleviate some verbosity in the | |
| 449 // impl. | |
| 450 using SBWhitelistId = ThreadSafeStateManager::SBWhitelistId; | |
| 451 using PrefixSetId = ThreadSafeStateManager::PrefixSetId; | |
| 452 using ReadTransaction = ThreadSafeStateManager::ReadTransaction; | |
| 453 using WriteTransaction = ThreadSafeStateManager::WriteTransaction; | |
| 454 | |
| 455 bool PrefixSetContainsUrl(const GURL& url, | |
| 456 PrefixSetId prefix_set_id, | |
| 457 std::vector<SBPrefix>* prefix_hits, | |
| 458 std::vector<SBFullHashResult>* cache_hits); | |
| 375 | 459 |
| 376 // Exposed for testing of PrefixSetContainsUrlHashes() on the | 460 // Exposed for testing of PrefixSetContainsUrlHashes() on the |
| 377 // PrefixSet backing kMalwareList. | 461 // PrefixSet backing kMalwareList. |
| 378 bool ContainsBrowseUrlHashesForTesting( | 462 bool ContainsBrowseUrlHashesForTesting( |
| 379 const std::vector<SBFullHash>& full_hashes, | 463 const std::vector<SBFullHash>& full_hashes, |
| 380 std::vector<SBPrefix>* prefix_hits, | 464 std::vector<SBPrefix>* prefix_hits, |
| 381 std::vector<SBFullHashResult>* cache_hits); | 465 std::vector<SBFullHashResult>* cache_hits); |
| 382 | 466 |
| 383 bool PrefixSetContainsUrlHashes( | 467 bool PrefixSetContainsUrlHashes(const std::vector<SBFullHash>& full_hashes, |
| 384 const std::vector<SBFullHash>& full_hashes, | 468 PrefixSetId prefix_set_id, |
| 385 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, | 469 std::vector<SBPrefix>* prefix_hits, |
| 386 std::vector<SBPrefix>* prefix_hits, | 470 std::vector<SBFullHashResult>* cache_hits); |
| 387 std::vector<SBFullHashResult>* cache_hits); | |
| 388 | 471 |
| 389 // Returns true if the whitelist is disabled or if any of the given hashes | 472 // Returns true if the whitelist is disabled or if any of the given hashes |
| 390 // matches the whitelist. | 473 // matches the whitelist. |
| 391 bool ContainsWhitelistedHashes(const SBWhitelist& whitelist, | 474 bool ContainsWhitelistedHashes(SBWhitelistId whitelist_id, |
| 392 const std::vector<SBFullHash>& hashes); | 475 const std::vector<SBFullHash>& hashes); |
| 393 | 476 |
| 394 // Return the browse_store_, download_store_, download_whitelist_store or | 477 // Return the browse_store_, download_store_, download_whitelist_store or |
| 395 // csd_whitelist_store_ based on list_id. | 478 // csd_whitelist_store_ based on list_id. |
| 396 SafeBrowsingStore* GetStore(int list_id); | 479 SafeBrowsingStore* GetStore(int list_id); |
| 397 | 480 |
| 398 // Deletes the files on disk. | 481 // Deletes the files on disk. |
| 399 bool Delete(); | 482 bool Delete(); |
| 400 | 483 |
| 401 // Load the prefix set in "|db_filename| Prefix Set" off disk, if available, | 484 // Load the prefix set in "|db_filename| Prefix Set" off disk, if available, |
| 402 // and stores it in |prefix_set|. |read_failure_type| provides a | 485 // and stores it in the PrefixSet identified by |prefix_set_id|. |
| 403 // caller-specific error code to be used on failure. | 486 // |read_failure_type| provides a caller-specific error code to be used on |
| 487 // failure. This method should only ever be called during initialization as | |
| 488 // it performs some disk IO while holding a transaction (for the sake of | |
| 489 // avoiding uncessary back-and-forth interactions with the lock during | |
| 490 // Init()). | |
| 404 void LoadPrefixSet(const base::FilePath& db_filename, | 491 void LoadPrefixSet(const base::FilePath& db_filename, |
| 405 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, | 492 ThreadSafeStateManager::WriteTransaction* txn, |
| 493 PrefixSetId prefix_set_id, | |
| 406 FailureType read_failure_type); | 494 FailureType read_failure_type); |
| 407 | 495 |
| 408 // Writes the current prefix set "|db_filename| Prefix Set" on disk. | 496 // Writes the current prefix set "|db_filename| Prefix Set" on disk. |
| 409 // |write_failure_type| provides a caller-specific error code to be used on | 497 // |write_failure_type| provides a caller-specific error code to be used on |
| 410 // failure. | 498 // failure. |
| 411 void WritePrefixSet(const base::FilePath& db_filename, | 499 void WritePrefixSet(const base::FilePath& db_filename, |
| 412 const safe_browsing::PrefixSet* prefix_set, | 500 const safe_browsing::PrefixSet* prefix_set, |
| 413 FailureType write_failure_type); | 501 FailureType write_failure_type); |
| 414 | 502 |
| 415 // Loads the given full-length hashes to the given whitelist. If the number | 503 // Loads the given full-length hashes to the given whitelist. If the number |
| 416 // of hashes is too large or if the kill switch URL is on the whitelist | 504 // of hashes is too large or if the kill switch URL is on the whitelist |
| 417 // we will whitelist everything. | 505 // we will whitelist everything. |
| 418 void LoadWhitelist(const std::vector<SBAddFullHash>& full_hashes, | 506 void LoadWhitelist(const std::vector<SBAddFullHash>& full_hashes, |
| 419 SBWhitelist* whitelist); | 507 SBWhitelistId whitelist_id); |
| 420 | 508 |
| 421 // Call this method if an error occured with the given whitelist. This will | 509 // Call this method if an error occured with the given whitelist. This will |
| 422 // result in all lookups to the whitelist to return true. | 510 // result in all lookups to the whitelist to return true. |
| 423 void WhitelistEverything(SBWhitelist* whitelist); | 511 void WhitelistEverything(SBWhitelistId whitelist_id); |
| 424 | 512 |
| 425 // Parses the IP blacklist from the given full-length hashes. | 513 // Parses the IP blacklist from the given full-length hashes. |
| 426 void LoadIpBlacklist(const std::vector<SBAddFullHash>& full_hashes); | 514 void LoadIpBlacklist(const std::vector<SBAddFullHash>& full_hashes); |
| 427 | 515 |
| 428 // Helpers for handling database corruption. | 516 // Helpers for handling database corruption. |
| 429 // |OnHandleCorruptDatabase()| runs |ResetDatabase()| and sets | 517 // |OnHandleCorruptDatabase()| runs |ResetDatabase()| and sets |
| 430 // |corruption_detected_|, |HandleCorruptDatabase()| posts | 518 // |corruption_detected_|, |HandleCorruptDatabase()| posts |
| 431 // |OnHandleCorruptDatabase()| to the current thread, to be run | 519 // |OnHandleCorruptDatabase()| to the current thread, to be run |
| 432 // after the current task completes. | 520 // after the current task completes. |
| 433 // TODO(shess): Wire things up to entirely abort the update | 521 // TODO(shess): Wire things up to entirely abort the update |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 446 // Returns the size in bytes of the store after the update. | 534 // Returns the size in bytes of the store after the update. |
| 447 int64 UpdateHashPrefixStore(const base::FilePath& store_filename, | 535 int64 UpdateHashPrefixStore(const base::FilePath& store_filename, |
| 448 SafeBrowsingStore* store, | 536 SafeBrowsingStore* store, |
| 449 FailureType failure_type); | 537 FailureType failure_type); |
| 450 | 538 |
| 451 // Updates a PrefixStore store for URLs (|url_store|) which is backed on disk | 539 // Updates a PrefixStore store for URLs (|url_store|) which is backed on disk |
| 452 // by a "|db_filename| Prefix Set" file. Specific failure types are provided | 540 // by a "|db_filename| Prefix Set" file. Specific failure types are provided |
| 453 // to highlight the specific store who made the initial request on failure. | 541 // to highlight the specific store who made the initial request on failure. |
| 454 // |store_full_hashes_in_prefix_set| dictates whether full_hashes from the | 542 // |store_full_hashes_in_prefix_set| dictates whether full_hashes from the |
| 455 // |url_store| should be cached in the |prefix_set| as well. | 543 // |url_store| should be cached in the |prefix_set| as well. |
| 456 void UpdatePrefixSetUrlStore( | 544 void UpdatePrefixSetUrlStore(const base::FilePath& db_filename, |
| 457 const base::FilePath& db_filename, | 545 SafeBrowsingStore* url_store, |
| 458 SafeBrowsingStore* url_store, | 546 PrefixSetId prefix_set_id, |
| 459 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, | 547 FailureType finish_failure_type, |
| 460 FailureType finish_failure_type, | 548 FailureType write_failure_type, |
| 461 FailureType write_failure_type, | 549 bool store_full_hashes_in_prefix_set); |
| 462 bool store_full_hashes_in_prefix_set); | |
| 463 | 550 |
| 464 void UpdateUrlStore(SafeBrowsingStore* url_store, | 551 void UpdateUrlStore(SafeBrowsingStore* url_store, |
| 465 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, | 552 PrefixSetId prefix_set_id, |
| 466 FailureType failure_type); | 553 FailureType failure_type); |
| 467 | 554 |
| 468 void UpdateWhitelistStore(const base::FilePath& store_filename, | 555 void UpdateWhitelistStore(const base::FilePath& store_filename, |
| 469 SafeBrowsingStore* store, | 556 SafeBrowsingStore* store, |
| 470 SBWhitelist* whitelist); | 557 SBWhitelistId whitelist_id); |
| 471 void UpdateIpBlacklistStore(); | 558 void UpdateIpBlacklistStore(); |
| 472 | 559 |
| 473 // Used to verify that various calls are made from the thread the | 560 // Returns a raw pointer to ThreadSafeStateManager's PrefixGetHashCache for |
| 474 // object was created on (i.e., the safe_browsing_thread). | 561 // testing. This should only be used in unit tests (where multi-threading and |
| 475 base::ThreadChecker thread_checker_; | 562 // synchronization are not problematic). |
| 563 PrefixGetHashCache* GetUnsynchronizedPrefixGetHashCacheForTesting(); | |
| 564 | |
| 565 ThreadSafeStateManager state_manager_; | |
| 476 | 566 |
| 477 // The base filename passed to Init(), used to generate the store and prefix | 567 // The base filename passed to Init(), used to generate the store and prefix |
| 478 // set filenames used to store data on disk. | 568 // set filenames used to store data on disk. |
| 479 base::FilePath filename_base_; | 569 base::FilePath filename_base_; |
| 480 | 570 |
| 481 // Underlying persistent store for chunk data. | 571 // Underlying persistent store for chunk data. |
| 482 // For browsing related (phishing and malware URLs) chunks and prefixes. | 572 // For browsing related (phishing and malware URLs) chunks and prefixes. |
| 483 scoped_ptr<SafeBrowsingStore> browse_store_; | 573 scoped_ptr<SafeBrowsingStore> browse_store_; |
| 484 | 574 |
| 485 // For download related (download URL and binary hash) chunks and prefixes. | 575 // For download related (download URL and binary hash) chunks and prefixes. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 498 | 588 |
| 499 // For side-effect free whitelist. | 589 // For side-effect free whitelist. |
| 500 scoped_ptr<SafeBrowsingStore> side_effect_free_whitelist_store_; | 590 scoped_ptr<SafeBrowsingStore> side_effect_free_whitelist_store_; |
| 501 | 591 |
| 502 // For IP blacklist. | 592 // For IP blacklist. |
| 503 scoped_ptr<SafeBrowsingStore> ip_blacklist_store_; | 593 scoped_ptr<SafeBrowsingStore> ip_blacklist_store_; |
| 504 | 594 |
| 505 // For unwanted software list. | 595 // For unwanted software list. |
| 506 scoped_ptr<SafeBrowsingStore> unwanted_software_store_; | 596 scoped_ptr<SafeBrowsingStore> unwanted_software_store_; |
| 507 | 597 |
| 508 // Lock for protecting access to variables that may be used on any threads. | |
| 509 // This includes all SBWhitelist's, PrefixSet's, and caches. | |
| 510 base::Lock lookup_lock_; | |
| 511 | |
| 512 SBWhitelist csd_whitelist_; | |
| 513 SBWhitelist download_whitelist_; | |
| 514 | |
| 515 // The IP blacklist should be small. At most a couple hundred IPs. | |
| 516 IPBlacklist ip_blacklist_; | |
| 517 | |
| 518 // Cache of gethash results for prefix stores. Entries should not be used if | |
| 519 // they are older than their expire_after field. Cached misses will have | |
| 520 // empty full_hashes field. Cleared on each update. | |
| 521 std::map<SBPrefix, SBCachedFullHashResult> prefix_gethash_cache_; | |
| 522 | |
| 523 // Set if corruption is detected during the course of an update. | 598 // Set if corruption is detected during the course of an update. |
| 524 // Causes the update functions to fail with no side effects, until | 599 // Causes the update functions to fail with no side effects, until |
| 525 // the next call to |UpdateStarted()|. | 600 // the next call to |UpdateStarted()|. |
| 526 bool corruption_detected_; | 601 bool corruption_detected_; |
| 527 | 602 |
| 528 // Set to true if any chunks are added or deleted during an update. | 603 // Set to true if any chunks are added or deleted during an update. |
| 529 // Used to optimize away database update. | 604 // Used to optimize away database update. |
| 530 bool change_detected_; | 605 bool change_detected_; |
|
mattm
2014/12/12 23:20:31
Should all the non-thread-safe members be moved to
gab
2014/12/15 23:02:30
Good point, do you think the SafeBrowsingStores sh
mattm
2014/12/23 02:09:45
I guess to make it more consistent putting them in
gab
2014/12/23 21:39:54
SG, how about we do this in a follow-up CL since t
mattm
2014/12/24 00:29:53
separate CL sounds good
| |
| 531 | 606 |
| 532 // PrefixSets to speed up lookups for particularly large lists. The PrefixSet | |
| 533 // themselves are never modified, instead a new one is swapped in on update | |
| 534 // while holding |lookup_lock_|. Any thread other than this class' main thread | |
| 535 // (which handles updates) must hold |lookup_lock_| before reading from these | |
| 536 // sets. | |
| 537 // TODO(gab): Enforce this by design. | |
| 538 scoped_ptr<const safe_browsing::PrefixSet> browse_prefix_set_; | |
| 539 scoped_ptr<const safe_browsing::PrefixSet> | |
| 540 side_effect_free_whitelist_prefix_set_; | |
| 541 scoped_ptr<const safe_browsing::PrefixSet> unwanted_software_prefix_set_; | |
| 542 | |
| 543 // Used to schedule resetting the database because of corruption. | 607 // Used to schedule resetting the database because of corruption. |
| 544 base::WeakPtrFactory<SafeBrowsingDatabaseNew> reset_factory_; | 608 base::WeakPtrFactory<SafeBrowsingDatabaseNew> reset_factory_; |
| 545 }; | 609 }; |
| 546 | 610 |
| 547 #endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_DATABASE_H_ | 611 #endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_DATABASE_H_ |
| OLD | NEW |