Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "chrome/browser/nacl_host/nacl_browser.h" | 5 #include "chrome/browser/nacl_host/nacl_browser.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| 11 #include "base/path_service.h" | 11 #include "base/path_service.h" |
| 12 #include "base/pickle.h" | 12 #include "base/pickle.h" |
| 13 #include "base/rand_util.h" | |
| 13 #include "base/strings/string_split.h" | 14 #include "base/strings/string_split.h" |
| 14 #include "base/win/windows_version.h" | 15 #include "base/win/windows_version.h" |
| 15 #include "build/build_config.h" | 16 #include "build/build_config.h" |
| 16 #include "chrome/common/chrome_paths.h" | 17 #include "chrome/common/chrome_paths.h" |
| 17 #include "chrome/common/chrome_paths_internal.h" | 18 #include "chrome/common/chrome_paths_internal.h" |
| 18 #include "chrome/common/chrome_switches.h" | 19 #include "chrome/common/chrome_switches.h" |
| 19 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
| 20 #include "extensions/common/url_pattern.h" | 21 #include "extensions/common/url_pattern.h" |
| 21 #include "googleurl/src/gurl.h" | 22 #include "googleurl/src/gurl.h" |
| 22 | 23 |
| 23 namespace { | 24 namespace { |
| 24 | 25 |
| 25 // An arbitrary delay to coalesce multiple writes to the cache. | 26 // An arbitrary delay to coalesce multiple writes to the cache. |
| 26 const int kValidationCacheCoalescingTimeMS = 6000; | 27 const int kValidationCacheCoalescingTimeMS = 6000; |
| 27 const char kValidationCacheSequenceName[] = "NaClValidationCache"; | 28 const char kValidationCacheSequenceName[] = "NaClValidationCache"; |
| 28 const base::FilePath::CharType kValidationCacheFileName[] = | 29 const base::FilePath::CharType kValidationCacheFileName[] = |
| 29 FILE_PATH_LITERAL("nacl_validation_cache.bin"); | 30 FILE_PATH_LITERAL("nacl_validation_cache.bin"); |
| 30 | 31 |
| 31 const bool kValidationCacheEnabledByDefault = true; | 32 const bool kValidationCacheEnabledByDefault = true; |
| 32 | 33 |
| 33 enum ValidationCacheStatus { | 34 enum ValidationCacheStatus { |
| 34 CACHE_MISS = 0, | 35 CACHE_MISS = 0, |
| 35 CACHE_HIT, | 36 CACHE_HIT, |
| 36 CACHE_MAX | 37 CACHE_MAX |
| 37 }; | 38 }; |
| 38 | 39 |
| 40 // Keep the cache bounded to an arbitrary size. If it's too small, useful | |
| 41 // entries could be evicted when multiple .nexes are loaded at once. On the | |
| 42 // other hand, entries are not always claimed, so the size of the cache will | |
|
Mark Seaborn
2013/05/24 20:21:58
Say "claimed (and hence removed)"? Otherwise it's
Nick Bray (chromium)
2013/05/24 21:35:24
Done.
| |
| 43 // likely saturate at its maximum size. | |
| 44 const int kFilePathCacheSize = 100; | |
| 45 | |
| 39 const base::FilePath::StringType NaClIrtName() { | 46 const base::FilePath::StringType NaClIrtName() { |
| 40 base::FilePath::StringType irt_name(FILE_PATH_LITERAL("nacl_irt_")); | 47 base::FilePath::StringType irt_name(FILE_PATH_LITERAL("nacl_irt_")); |
| 41 | 48 |
| 42 #if defined(ARCH_CPU_X86_FAMILY) | 49 #if defined(ARCH_CPU_X86_FAMILY) |
| 43 #if defined(ARCH_CPU_X86_64) | 50 #if defined(ARCH_CPU_X86_64) |
| 44 bool is64 = true; | 51 bool is64 = true; |
| 45 #elif defined(OS_WIN) | 52 #elif defined(OS_WIN) |
| 46 bool is64 = (base::win::OSInfo::GetInstance()->wow64_status() == | 53 bool is64 = (base::win::OSInfo::GetInstance()->wow64_status() == |
| 47 base::win::OSInfo::WOW64_ENABLED); | 54 base::win::OSInfo::WOW64_ENABLED); |
| 48 #else | 55 #else |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Query", status, CACHE_MAX); | 106 UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Query", status, CACHE_MAX); |
| 100 } | 107 } |
| 101 | 108 |
| 102 void LogCacheSet(ValidationCacheStatus status) { | 109 void LogCacheSet(ValidationCacheStatus status) { |
| 103 // Bucket zero is reserved for future use. | 110 // Bucket zero is reserved for future use. |
| 104 UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Set", status, CACHE_MAX); | 111 UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Set", status, CACHE_MAX); |
| 105 } | 112 } |
| 106 | 113 |
| 107 } // namespace | 114 } // namespace |
| 108 | 115 |
| 116 namespace nacl { | |
| 117 | |
| 118 void OpenNaClExecutableImpl(const base::FilePath& file_path, | |
| 119 base::PlatformFile* file) { | |
| 120 // Get a file descriptor. On Windows, we need 'GENERIC_EXECUTE' in order to | |
| 121 // memory map the executable. | |
| 122 // IMPORTANT: This file descriptor must not have write access - that could | |
| 123 // allow a NaCl inner sandbox escape. | |
| 124 base::PlatformFileError error_code; | |
| 125 *file = base::CreatePlatformFile( | |
| 126 file_path, | |
| 127 (base::PLATFORM_FILE_OPEN | | |
| 128 base::PLATFORM_FILE_READ | | |
| 129 base::PLATFORM_FILE_EXECUTE), // Windows only flag. | |
| 130 NULL, | |
| 131 &error_code); | |
| 132 if (error_code != base::PLATFORM_FILE_OK) { | |
| 133 *file = base::kInvalidPlatformFileValue; | |
| 134 return; | |
| 135 } | |
| 136 // Check that the file does not reference a directory. Returning a descriptor | |
| 137 // to an extension directory could allow an outer sandbox escape. openat | |
|
Mark Seaborn
2013/05/24 20:21:58
"openat" -> "openat()" to be clearer what you're r
Nick Bray (chromium)
2013/05/24 21:35:24
Done.
| |
| 138 // could be used to traverse into the file system. | |
| 139 base::PlatformFileInfo file_info; | |
| 140 if (!base::GetPlatformFileInfo(*file, &file_info) || | |
| 141 file_info.is_directory) { | |
| 142 base::ClosePlatformFile(*file); | |
| 143 *file = base::kInvalidPlatformFileValue; | |
| 144 return; | |
| 145 } | |
| 146 } | |
| 147 | |
| 148 } | |
| 149 | |
| 109 NaClBrowser::NaClBrowser() | 150 NaClBrowser::NaClBrowser() |
| 110 : weak_factory_(this), | 151 : weak_factory_(this), |
| 111 irt_platform_file_(base::kInvalidPlatformFileValue), | 152 irt_platform_file_(base::kInvalidPlatformFileValue), |
| 112 irt_filepath_(), | 153 irt_filepath_(), |
| 113 irt_state_(NaClResourceUninitialized), | 154 irt_state_(NaClResourceUninitialized), |
| 114 debug_patterns_(), | 155 debug_patterns_(), |
| 115 inverse_debug_patterns_(false), | 156 inverse_debug_patterns_(false), |
| 116 validation_cache_file_path_(), | 157 validation_cache_file_path_(), |
| 117 validation_cache_is_enabled_( | 158 validation_cache_is_enabled_( |
| 118 CheckEnvVar("NACL_VALIDATION_CACHE", | 159 CheckEnvVar("NACL_VALIDATION_CACHE", |
| 119 kValidationCacheEnabledByDefault)), | 160 kValidationCacheEnabledByDefault)), |
| 120 validation_cache_is_modified_(false), | 161 validation_cache_is_modified_(false), |
| 121 validation_cache_state_(NaClResourceUninitialized), | 162 validation_cache_state_(NaClResourceUninitialized), |
| 163 path_cache_(kFilePathCacheSize), | |
| 122 ok_(true) { | 164 ok_(true) { |
| 123 InitIrtFilePath(); | 165 InitIrtFilePath(); |
| 124 InitValidationCacheFilePath(); | 166 InitValidationCacheFilePath(); |
| 125 } | 167 } |
| 126 | 168 |
| 127 NaClBrowser::~NaClBrowser() { | 169 NaClBrowser::~NaClBrowser() { |
| 128 if (irt_platform_file_ != base::kInvalidPlatformFileValue) | 170 if (irt_platform_file_ != base::kInvalidPlatformFileValue) |
| 129 base::ClosePlatformFile(irt_platform_file_); | 171 base::ClosePlatformFile(irt_platform_file_); |
| 130 } | 172 } |
| 131 | 173 |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 365 void NaClBrowser::WaitForResources(const base::Closure& reply) { | 407 void NaClBrowser::WaitForResources(const base::Closure& reply) { |
| 366 waiting_.push_back(reply); | 408 waiting_.push_back(reply); |
| 367 EnsureAllResourcesAvailable(); | 409 EnsureAllResourcesAvailable(); |
| 368 CheckWaiting(); | 410 CheckWaiting(); |
| 369 } | 411 } |
| 370 | 412 |
| 371 const base::FilePath& NaClBrowser::GetIrtFilePath() { | 413 const base::FilePath& NaClBrowser::GetIrtFilePath() { |
| 372 return irt_filepath_; | 414 return irt_filepath_; |
| 373 } | 415 } |
| 374 | 416 |
| 417 void NaClBrowser::PutFilePath(const base::FilePath& path, uint64 *file_token_lo, | |
|
Mark Seaborn
2013/05/24 20:21:58
Fix "*" spacing style
Nick Bray (chromium)
2013/05/24 21:35:24
Done.
| |
| 418 uint64 *file_token_hi) { | |
|
Mark Seaborn
2013/05/24 20:21:58
Fix indentation
Nick Bray (chromium)
2013/05/24 21:35:24
Done.
| |
| 419 while (true) { | |
| 420 uint64 file_token[2] = {base::RandUint64(), base::RandUint64()}; | |
| 421 // A zero file_token indicates there is no file_token, if we get zero, ask | |
| 422 // for another number. | |
| 423 if (file_token[0] != 0 || file_token[1] != 0) { | |
| 424 // If the file_token is in use, ask for another number. | |
| 425 std::string key(reinterpret_cast<char *>(file_token), sizeof(file_token)); | |
|
Mark Seaborn
2013/05/24 20:21:58
Spacing style should be "char*"
Nick Bray (chromium)
2013/05/24 21:35:24
Done.
| |
| 426 PathCacheType::iterator iter = path_cache_.Peek(key); | |
| 427 if (iter == path_cache_.end()) { | |
| 428 path_cache_.Put(key, path); | |
| 429 *file_token_lo = file_token[0]; | |
| 430 *file_token_hi = file_token[1]; | |
| 431 break; | |
| 432 } | |
| 433 } | |
| 434 } | |
| 435 } | |
| 436 | |
| 437 bool NaClBrowser::GetFilePath(uint64 file_token_lo, uint64 file_token_hi, | |
| 438 base::FilePath* path) { | |
| 439 uint64 file_token[2] = {file_token_lo, file_token_hi}; | |
| 440 std::string key(reinterpret_cast<char *>(file_token), sizeof(file_token)); | |
|
Mark Seaborn
2013/05/24 20:21:58
Spacing style should be "char*"
Nick Bray (chromium)
2013/05/24 21:35:24
Done.
| |
| 441 PathCacheType::iterator iter = path_cache_.Peek(key); | |
|
Mark Seaborn
2013/05/24 20:21:58
Fix spacing (you have 2 spaces before '=')
Nick Bray (chromium)
2013/05/24 21:35:24
Done.
| |
| 442 if (iter == path_cache_.end()) { | |
| 443 *path = base::FilePath(FILE_PATH_LITERAL("")); | |
| 444 return false; | |
| 445 } | |
| 446 *path = iter->second; | |
| 447 path_cache_.Erase(iter); | |
| 448 return true; | |
| 449 } | |
| 450 | |
| 451 | |
| 375 bool NaClBrowser::QueryKnownToValidate(const std::string& signature, | 452 bool NaClBrowser::QueryKnownToValidate(const std::string& signature, |
| 376 bool off_the_record) { | 453 bool off_the_record) { |
| 377 if (off_the_record) { | 454 if (off_the_record) { |
| 378 // If we're off the record, don't reorder the main cache. | 455 // If we're off the record, don't reorder the main cache. |
| 379 return validation_cache_.QueryKnownToValidate(signature, false) || | 456 return validation_cache_.QueryKnownToValidate(signature, false) || |
| 380 off_the_record_validation_cache_.QueryKnownToValidate(signature, true); | 457 off_the_record_validation_cache_.QueryKnownToValidate(signature, true); |
| 381 } else { | 458 } else { |
| 382 bool result = validation_cache_.QueryKnownToValidate(signature, true); | 459 bool result = validation_cache_.QueryKnownToValidate(signature, true); |
| 383 LogCacheQuery(result ? CACHE_HIT : CACHE_MISS); | 460 LogCacheQuery(result ? CACHE_HIT : CACHE_MISS); |
| 384 // Queries can modify the MRU order of the cache. | 461 // Queries can modify the MRU order of the cache. |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 465 // because it can degrade the responsiveness of the browser. | 542 // because it can degrade the responsiveness of the browser. |
| 466 // The task is sequenced so that multiple writes happen in order. | 543 // The task is sequenced so that multiple writes happen in order. |
| 467 content::BrowserThread::PostBlockingPoolSequencedTask( | 544 content::BrowserThread::PostBlockingPoolSequencedTask( |
| 468 kValidationCacheSequenceName, | 545 kValidationCacheSequenceName, |
| 469 FROM_HERE, | 546 FROM_HERE, |
| 470 base::Bind(WriteCache, validation_cache_file_path_, | 547 base::Bind(WriteCache, validation_cache_file_path_, |
| 471 base::Owned(pickle))); | 548 base::Owned(pickle))); |
| 472 } | 549 } |
| 473 validation_cache_is_modified_ = false; | 550 validation_cache_is_modified_ = false; |
| 474 } | 551 } |
| OLD | NEW |